home *** CD-ROM | disk | FTP | other *** search
/ Enter 2006 September / Enter 09 2006.iso / Internet / SpamExperts Home 1.1 / SpamExperts Home.exe / lib / spamexperts.modules / dns / rdata.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2006-07-14  |  14.1 KB  |  451 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. """DNS rdata.
  5.  
  6. @var _rdata_modules: A dictionary mapping a (rdclass, rdtype) tuple to
  7. the module which implements that type.
  8. @type _rdata_modules: dict
  9. @var _module_prefix: The prefix to use when forming modules names.  The
  10. default is 'dns.rdtypes'.  Changing this value will break the library.
  11. @type _module_prefix: string
  12. @var _hex_chunk: At most this many octets that will be represented in each
  13. chunk of hexstring that _hexify() produces before whitespace occurs.
  14. @type _hex_chunk: int"""
  15. import dns.exception as dns
  16. import dns.rdataclass as dns
  17. import dns.rdatatype as dns
  18. import dns.tokenizer as dns
  19. _hex_chunksize = 32
  20.  
  21. def _hexify(data, chunksize = None):
  22.     '''Convert a binary string into its hex encoding, broken up into chunks
  23.     of I{chunksize} characters separated by a space.
  24.  
  25.     @param data: the binary string
  26.     @type data: string
  27.     @param chunksize: the chunk size.  Default is L{dns.rdata._hex_chunksize}
  28.     @rtype: string
  29.     '''
  30.     if chunksize is None:
  31.         chunksize = _hex_chunksize
  32.     
  33.     hex = data.encode('hex_codec')
  34.     l = len(hex)
  35.     if l > chunksize:
  36.         chunks = []
  37.         i = 0
  38.         while i < l:
  39.             chunks.append(hex[i:i + chunksize])
  40.             i += chunksize
  41.         hex = ' '.join(chunks)
  42.     
  43.     return hex
  44.  
  45. _base64_chunksize = 32
  46.  
  47. def _base64ify(data, chunksize = None):
  48.     '''Convert a binary string into its base64 encoding, broken up into chunks
  49.     of I{chunksize} characters separated by a space.
  50.  
  51.     @param data: the binary string
  52.     @type data: string
  53.     @param chunksize: the chunk size.  Default is
  54.     L{dns.rdata._base64_chunksize}
  55.     @rtype: string
  56.     '''
  57.     if chunksize is None:
  58.         chunksize = _base64_chunksize
  59.     
  60.     b64 = data.encode('base64_codec')
  61.     b64 = b64.replace('\n', '')
  62.     l = len(b64)
  63.     if l > chunksize:
  64.         chunks = []
  65.         i = 0
  66.         while i < l:
  67.             chunks.append(b64[i:i + chunksize])
  68.             i += chunksize
  69.         b64 = ' '.join(chunks)
  70.     
  71.     return b64
  72.  
  73. __escaped = {
  74.     '"': True,
  75.     '\\': True }
  76.  
  77. def _escapify(qstring):
  78.     '''Escape the characters in a quoted string which need it.
  79.  
  80.     @param qstring: the string
  81.     @type qstring: string
  82.     @returns: the escaped string
  83.     @rtype: string
  84.     '''
  85.     text = ''
  86.     for c in qstring:
  87.         if c in __escaped:
  88.             text += '\\' + c
  89.             continue
  90.         if ord(c) >= 32 and ord(c) < 127:
  91.             text += c
  92.             continue
  93.         text += '\\%03d' % ord(c)
  94.     
  95.     return text
  96.  
  97.  
  98. def _truncate_bitmap(what):
  99.     """Determine the index of greatest byte that isn't all zeros, and
  100.     return the bitmap that contains all the bytes less than that index.
  101.  
  102.     @param what: a string of octets representing a bitmap.
  103.     @type what: string
  104.     @rtype: string
  105.     """
  106.     for i in xrange(len(what) - 1, -1, -1):
  107.         if what[i] != '\x00':
  108.             break
  109.             continue
  110.     
  111.     return ''.join(what[0:i + 1])
  112.  
  113.  
  114. class Rdata(object):
  115.     '''Base class for all DNS rdata types.
  116.     '''
  117.     __slots__ = [
  118.         'rdclass',
  119.         'rdtype']
  120.     
  121.     def __init__(self, rdclass, rdtype):
  122.         '''Initialize an rdata.
  123.         @param rdclass: The rdata class
  124.         @type rdclass: int
  125.         @param rdtype: The rdata type
  126.         @type rdtype: int
  127.         '''
  128.         self.rdclass = rdclass
  129.         self.rdtype = rdtype
  130.  
  131.     
  132.     def covers(self):
  133.         '''DNS SIG/RRSIG rdatas apply to a specific type; this type is
  134.         returned by the covers() function.  If the rdata type is not
  135.         SIG or RRSIG, dns.rdatatype.NONE is returned.  This is useful when
  136.         creating rdatasets, allowing the rdataset to contain only RRSIGs
  137.         of a particular type, e.g. RRSIG(NS).
  138.         @rtype: int
  139.         '''
  140.         return dns.rdatatype.NONE
  141.  
  142.     
  143.     def extended_rdatatype(self):
  144.         '''Return a 32-bit type value, the least significant 16 bits of
  145.         which are the ordinary DNS type, and the upper 16 bits of which are
  146.         the "covered" type, if any.
  147.         @rtype: int
  148.         '''
  149.         return self.covers() << 16 | self.rdtype
  150.  
  151.     
  152.     def to_text(self, origin = None, relativize = True, **kw):
  153.         '''Convert an rdata to text format.
  154.         @rtype: string
  155.         '''
  156.         raise NotImplementedError
  157.  
  158.     
  159.     def to_wire(self, file, compress = None, origin = None):
  160.         '''Convert an rdata to wire format.
  161.         @rtype: string
  162.         '''
  163.         raise NotImplementedError
  164.  
  165.     
  166.     def __repr__(self):
  167.         covers = self.covers()
  168.         if covers == dns.rdatatype.NONE:
  169.             ctext = ''
  170.         else:
  171.             ctext = '(' + dns.rdatatype.to_text(covers) + ')'
  172.         return '<DNS ' + dns.rdataclass.to_text(self.rdclass) + ' ' + dns.rdatatype.to_text(self.rdtype) + ctext + ' rdata: ' + str(self) + '>'
  173.  
  174.     
  175.     def __str__(self):
  176.         return self.to_text()
  177.  
  178.     
  179.     def _cmp(self, other):
  180.         '''Compare an rdata with another rdata of the same rdtype and
  181.         rdclass.  Return < 0 if self < other in the DNSSEC ordering,
  182.         0 if self == other, and > 0 if self > other.
  183.         '''
  184.         raise NotImplementedError
  185.  
  186.     
  187.     def __eq__(self, other):
  188.         if not isinstance(other, Rdata):
  189.             return False
  190.         
  191.         if self.rdclass != other.rdclass or self.rdtype != other.rdtype:
  192.             return False
  193.         
  194.         return self._cmp(other) == 0
  195.  
  196.     
  197.     def __ne__(self, other):
  198.         if not isinstance(other, Rdata):
  199.             return True
  200.         
  201.         if self.rdclass != other.rdclass or self.rdtype != other.rdtype:
  202.             return True
  203.         
  204.         return self._cmp(other) != 0
  205.  
  206.     
  207.     def __lt__(self, other):
  208.         if not isinstance(other, Rdata) and self.rdclass != other.rdclass or self.rdtype != other.rdtype:
  209.             return NotImplemented
  210.         
  211.         return self._cmp(other) < 0
  212.  
  213.     
  214.     def __le__(self, other):
  215.         if not isinstance(other, Rdata) and self.rdclass != other.rdclass or self.rdtype != other.rdtype:
  216.             return NotImplemented
  217.         
  218.         return self._cmp(other) <= 0
  219.  
  220.     
  221.     def __ge__(self, other):
  222.         if not isinstance(other, Rdata) and self.rdclass != other.rdclass or self.rdtype != other.rdtype:
  223.             return NotImplemented
  224.         
  225.         return self._cmp(other) >= 0
  226.  
  227.     
  228.     def __gt__(self, other):
  229.         if not isinstance(other, Rdata) and self.rdclass != other.rdclass or self.rdtype != other.rdtype:
  230.             return NotImplemented
  231.         
  232.         return self._cmp(other) > 0
  233.  
  234.     
  235.     def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
  236.         '''Build an rdata object from text format.
  237.  
  238.         @param rdclass: The rdata class
  239.         @type rdclass: int
  240.         @param rdtype: The rdata type
  241.         @type rdtype: int
  242.         @param tok: The tokenizer
  243.         @type tok: dns.tokenizer.Tokenizer
  244.         @param origin: The origin to use for relative names
  245.         @type origin: dns.name.Name
  246.         @param relativize: should names be relativized?
  247.         @type relativize: bool
  248.         @rtype: dns.rdata.Rdata instance
  249.         '''
  250.         raise NotImplementedError
  251.  
  252.     from_text = classmethod(from_text)
  253.     
  254.     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
  255.         '''Build an rdata object from wire format
  256.         
  257.         @param rdclass: The rdata class
  258.         @type rdclass: int
  259.         @param rdtype: The rdata type
  260.         @type rdtype: int
  261.         @param wire: The wire-format message
  262.         @type wire: string
  263.         @param current: The offet in wire of the beginning of the rdata.
  264.         @type current: int
  265.         @param rdlen: The length of the wire-format rdata
  266.         @type rdlen: int
  267.         @param origin: The origin to use for relative names
  268.         @type origin: dns.name.Name
  269.         @rtype: dns.rdata.Rdata instance
  270.         '''
  271.         raise NotImplementedError
  272.  
  273.     from_wire = classmethod(from_wire)
  274.     
  275.     def choose_relativity(self, origin = None, relativize = True):
  276.         '''Convert any domain names in the rdata to the specified
  277.         relativization.
  278.         '''
  279.         pass
  280.  
  281.  
  282.  
  283. class GenericRdata(Rdata):
  284.     '''Generate Rdata Class
  285.  
  286.     This class is used for rdata types for which we have no better
  287.     implementation.  It implements the DNS "unknown RRs" scheme.
  288.     '''
  289.     __slots__ = [
  290.         'data']
  291.     
  292.     def __init__(self, rdclass, rdtype, data):
  293.         super(GenericRdata, self).__init__(rdclass, rdtype)
  294.         self.data = data
  295.  
  296.     
  297.     def to_text(self, origin = None, relativize = True, **kw):
  298.         return '\\# %d ' % len(self.data) + _hexify(self.data)
  299.  
  300.     
  301.     def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
  302.         if tok.get_string() != '\\#':
  303.             raise dns.exception.SyntaxError, 'generic rdata does not start with \\#'
  304.         
  305.         length = tok.get_int()
  306.         chunks = []
  307.         while None:
  308.             (ttype, value) = tok.get()
  309.             if ttype == dns.tokenizer.EOL or ttype == dns.tokenizer.EOF:
  310.                 break
  311.             
  312.         hex = ''.join(chunks)
  313.         data = hex.decode('hex_codec')
  314.         if len(data) != length:
  315.             raise dns.exception.SyntaxError, 'generic rdata hex data has wrong length'
  316.         
  317.         return cls(rdclass, rdtype, data)
  318.  
  319.     from_text = classmethod(from_text)
  320.     
  321.     def to_wire(self, file, compress = None, origin = None):
  322.         file.write(self.data)
  323.  
  324.     
  325.     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
  326.         return cls(rdclass, rdtype, wire[current:current + rdlen])
  327.  
  328.     from_wire = classmethod(from_wire)
  329.     
  330.     def _cmp(self, other):
  331.         return cmp(self.data, other.data)
  332.  
  333.  
  334. _rdata_modules = { }
  335. _module_prefix = 'dns.rdtypes'
  336.  
  337. def get_rdata_class(rdclass, rdtype):
  338.     
  339.     def import_module(name):
  340.         mod = __import__(name)
  341.         components = name.split('.')
  342.         for comp in components[1:]:
  343.             mod = getattr(mod, comp)
  344.         
  345.         return mod
  346.  
  347.     mod = _rdata_modules.get((rdclass, rdtype))
  348.     rdclass_text = dns.rdataclass.to_text(rdclass)
  349.     rdtype_text = dns.rdatatype.to_text(rdtype)
  350.     rdtype_text = rdtype_text.replace('-', '_')
  351.     if not mod:
  352.         mod = _rdata_modules.get((dns.rdatatype.ANY, rdtype))
  353.         if not mod:
  354.             
  355.             try:
  356.                 mod = import_module('.'.join([
  357.                     _module_prefix,
  358.                     rdclass_text,
  359.                     rdtype_text]))
  360.                 _rdata_modules[(rdclass, rdtype)] = mod
  361.             except ImportError:
  362.                 
  363.                 try:
  364.                     mod = import_module('.'.join([
  365.                         _module_prefix,
  366.                         'ANY',
  367.                         rdtype_text]))
  368.                     _rdata_modules[(dns.rdataclass.ANY, rdtype)] = mod
  369.                 except ImportError:
  370.                     mod = None
  371.                 except:
  372.                     None<EXCEPTION MATCH>ImportError
  373.                 
  374.  
  375.                 None<EXCEPTION MATCH>ImportError
  376.             
  377.  
  378.         None<EXCEPTION MATCH>ImportError
  379.     
  380.     if mod:
  381.         cls = getattr(mod, rdtype_text)
  382.     else:
  383.         cls = GenericRdata
  384.     return cls
  385.  
  386.  
  387. def from_text(rdclass, rdtype, tok, origin = None, relativize = True):
  388.     '''Build an rdata object from text format.
  389.  
  390.     This function attempts to dynamically load a class which
  391.     implements the specified rdata class and type.  If there is no
  392.     class-and-type-specific implementation, the GenericRdata class
  393.     is used.
  394.  
  395.     Once a class is chosen, its from_text() class method is called
  396.     with the parameters to this function.
  397.  
  398.     @param rdclass: The rdata class
  399.     @type rdclass: int
  400.     @param rdtype: The rdata type
  401.     @type rdtype: int
  402.     @param tok: The tokenizer
  403.     @type tok: dns.tokenizer.Tokenizer
  404.     @param origin: The origin to use for relative names
  405.     @type origin: dns.name.Name
  406.     @param relativize: Should names be relativized?
  407.     @type relativize: bool
  408.     @rtype: dns.rdata.Rdata instance'''
  409.     if isinstance(tok, str):
  410.         tok = dns.tokenizer.Tokenizer(tok)
  411.     
  412.     cls = get_rdata_class(rdclass, rdtype)
  413.     if cls != GenericRdata:
  414.         token = tok.get()
  415.         tok.unget(token)
  416.         if token[0] == dns.tokenizer.IDENTIFIER and token[1] == '\\#':
  417.             rdata = GenericRdata.from_text(rdclass, rdtype, tok, origin, relativize)
  418.             return from_wire(rdclass, rdtype, rdata.data, 0, len(rdata.data), origin)
  419.         
  420.     
  421.     return cls.from_text(rdclass, rdtype, tok, origin, relativize)
  422.  
  423.  
  424. def from_wire(rdclass, rdtype, wire, current, rdlen, origin = None):
  425.     '''Build an rdata object from wire format
  426.  
  427.     This function attempts to dynamically load a class which
  428.     implements the specified rdata class and type.  If there is no
  429.     class-and-type-specific implementation, the GenericRdata class
  430.     is used.
  431.  
  432.     Once a class is chosen, its from_wire() class method is called
  433.     with the parameters to this function.
  434.     
  435.     @param rdclass: The rdata class
  436.     @type rdclass: int
  437.     @param rdtype: The rdata type
  438.     @type rdtype: int
  439.     @param wire: The wire-format message
  440.     @type wire: string
  441.     @param current: The offet in wire of the beginning of the rdata.
  442.     @type current: int
  443.     @param rdlen: The length of the wire-format rdata
  444.     @type rdlen: int
  445.     @param origin: The origin to use for relative names
  446.     @type origin: dns.name.Name
  447.     @rtype: dns.rdata.Rdata instance'''
  448.     cls = get_rdata_class(rdclass, rdtype)
  449.     return cls.from_wire(rdclass, rdtype, wire, current, rdlen, origin)
  450.  
  451.